package com.chart.chart.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chart.chart.domian.ChartConfigsUser;
import com.chart.chart.domian.ChartConfigsUserNew;
import com.chart.chart.domian.ChartFiles;
import com.chart.chart.domian.ChartFilesNew;
import com.chart.chart.mapper.ChartConfigsUserMapper;
import com.chart.chart.mapper.ChartFilesMapper;
import com.chart.chart.service.IChartFilesService;
import com.chart.common.core.domain.entity.ChartRecord;
import com.chart.common.dto.ChartConfigUserDTO;
import com.chart.common.dto.ChartFileTreeDTO;
import com.chart.common.dto.ChartFolderTreeDTO;
import com.chart.common.dto.ChartRecordDTO;
import com.chart.common.utils.SecurityUtils;
import com.chart.system.mapper.ChartFilesNewMapper;
import com.chart.system.mapper.ChartRecordMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ChartFilesServiceImpl extends ServiceImpl<ChartFilesMapper, ChartFiles> implements IChartFilesService {

    @Autowired
    private ChartFilesMapper chartFilesMapper;

    @Autowired
    private ChartConfigsUserMapper chartConfigsUserMapper;

    @Autowired
    private  ChartRecordMapper chartRecordMapper;

    @Override
    public List<ChartFileTreeDTO> getFolderFileTree(String name) {
        Long userId = SecurityUtils.getUserId();

        List<ChartFiles> allFolders = chartFilesMapper.selectFilesByName(name, userId);
        List<ChartConfigsUser> allFiles = chartConfigsUserMapper.selectConfigsByName(name, userId);

        if (name != null) {

            List<ChartFileTreeDTO> matchedFolders = allFolders.stream()
                    .filter(folder -> folder.getFileName() != null && folder.getFileName().contains(name))
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());


            List<ChartConfigUserDTO> matchedFiles = allFiles.stream()
                    .filter(file -> file.getChartName() != null && file.getChartName().contains(name))
                    .map(this::convertFileToDTO)
                    .collect(Collectors.toList());


            if (!matchedFolders.isEmpty() || !matchedFiles.isEmpty()) {
                ChartFileTreeDTO matchedNode = new ChartFileTreeDTO();
                matchedNode.setFileName("我的生成");
                matchedNode.setChildren(matchedFolders);
                matchedNode.setFiles(matchedFiles);
                return Arrays.asList(matchedNode);
            }
        }


        List<ChartFileTreeDTO> folderDTOList = allFolders.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
        List<ChartConfigUserDTO> fileDTOList = allFiles.stream()
                .map(this::convertFileToDTO)
                .collect(Collectors.toList());

        Map<Long, List<ChartConfigUserDTO>> filesByFolderId = fileDTOList.stream()
                .filter(file -> file.getFileId() != null)
                .collect(Collectors.groupingBy(ChartConfigUserDTO::getFileId));
        List<ChartConfigUserDTO> rootFiles = fileDTOList.stream()
                .filter(file -> file.getFileId() == null)
                .collect(Collectors.toList());

        List<ChartFileTreeDTO> rootFolders = buildTree(folderDTOList, filesByFolderId, null);

        ChartFileTreeDTO rootNode = new ChartFileTreeDTO();
        rootNode.setFileName("我的生成");
        rootNode.setFiles(rootFiles);
        rootNode.setChildren(rootFolders);

        return Arrays.asList(rootNode);
    }

    @Override

    // 新增的移动文件或文件夹的方法
    public boolean moveFileOrFolder(Long folderId, Long targetParentId, Long userId) {
        // 确保 folderId 不为空
        if (folderId == null) {
            log.warn("folderId 不能为空");
            throw new IllegalArgumentException("folderId 不能为空");
        }

        // 检查源文件夹或文件是否存在且属于该用户
        ChartFiles sourceFolder = chartFilesMapper.selectById(folderId);
        if (sourceFolder == null) {
            log.warn("源文件夹未找到: {}", folderId);
            return false; // 移动失败
        }

        // 检查是否需要更新 chart_files 表
        if (sourceFolder.getUserId().equals(userId)) {
            // 如果目标父 ID 为空，清空 parentId
            if (targetParentId == null) {
                sourceFolder.setParentId(null);
                chartFilesMapper.updateById(sourceFolder);
                return true; // 移动成功
            } else {
                // 否则更新为目标父 ID
                sourceFolder.setParentId(targetParentId);
                chartFilesMapper.updateById(sourceFolder);
            }
        } else {
            log.warn("文件夹不属于用户: userId={}, folderId={}", userId, folderId);
            return false; // 移动失败
        }

        // 检查文件是否存在且属于该用户
        ChartConfigsUser sourceFile = chartConfigsUserMapper.selectById(folderId);
        if (sourceFile != null && sourceFile.getUserId().equals(userId)) {
            // 如果目标父 ID 为空，清空 file_id
            if (targetParentId == null) {
                sourceFile.setFileId(null);
                chartConfigsUserMapper.updateById(sourceFile);
                return true; // 移动成功
            } else {
                // 否则更新为目标父 ID
                sourceFile.setFileId(targetParentId);
                chartConfigsUserMapper.updateById(sourceFile);
            }
        }

        return false; // 默认返回失败
    }


    // 递归方法构建树状结构
    private List<ChartFileTreeDTO> buildTree(List<ChartFileTreeDTO> folderList,
                                             Map<Long, List<ChartConfigUserDTO>> filesByFolderId,
                                             Long parentId) {
        return folderList.stream()
                // 如果 parentId 是 null 则选择根层级，或者 parentId 相等的情况下才会递归添加到子层级
                .filter(folder -> (parentId == null && folder.getParentId() == null) ||
                        (parentId != null && parentId.equals(folder.getParentId())))
                .map(folder -> {
                    // 设置文件列表，file_id 为空的文件也会在根层级
                    if (parentId == null) {
                        List<ChartConfigUserDTO> rootFiles = filesByFolderId.get(null);
                        if (rootFiles != null) {
                            folder.setFiles(rootFiles);
                        }
                    }
                    folder.setFiles(filesByFolderId.get(folder.getFileId()));

                    // 递归查找子文件夹
                    folder.setChildren(buildTree(folderList, filesByFolderId, folder.getFileId()));
                    return folder;
                })
                .collect(Collectors.toList());
    }

    // 将 ChartFiles 转换为 ChartFileTreeDTO
    private ChartFileTreeDTO convertToDTO(ChartFiles chartFile) {
        ChartFileTreeDTO dto = new ChartFileTreeDTO();
        dto.setFileId(chartFile.getFileId());
        dto.setFileName(chartFile.getFileName());
        dto.setParentId(chartFile.getParentId());
        return dto;
    }

    // 将 ChartConfigsUser 转换为 ChartConfigUserDTO
    private ChartConfigUserDTO convertFileToDTO(ChartConfigsUser chartConfigUser) {
        ChartConfigUserDTO dto = new ChartConfigUserDTO();
        dto.setId(chartConfigUser.getId());
        dto.setChartName(chartConfigUser.getChartName());
        dto.setFileId(chartConfigUser.getFileId());
        dto.setChartValue(chartConfigUser.getChartValue());
        dto.setImageUrl(chartConfigUser.getImageUrl()); // 设置 imageUrl
        return dto;
    }

    @Override
    public boolean moveFolder(Long folderId, Long targetParentId, Long userId) {
        // 检查 folderId 和 userId 的有效性
        if (folderId == null || folderId <= 0) {
            throw new IllegalArgumentException("无效的文件夹 ID。");
        }
        if (userId == null || userId <= 0) {
            throw new IllegalArgumentException("无效的用户 ID。");
        }

        // 获取文件夹的版本号，确保文件夹存在  防止多同时修改一条数据
        Integer version = chartFilesMapper.selectByfileId(folderId);
        if (version == null) {
            throw new RuntimeException("文件夹不存在，无法移动。");
        }
        // 尝试更新父文件夹 ID，确保版本号匹配
        int rowsUpdated = chartFilesMapper.updataParentId(folderId, targetParentId, userId, version);
        if (rowsUpdated > 0) {
            log.info("文件夹移动成功: folderId={}, targetParentId={}, userId={}", folderId, targetParentId, userId);
            return true;
        } else {
            log.warn("文件夹移动失败，可能由于版本号不匹配或文件夹不存在: folderId={}, targetParentId={}, userId={}, version={}", folderId, targetParentId, userId, version);
            return false;
        }
    }





    @Override
    public boolean moveFile(Long fileId, Long targetParentId, Long userId) {
        if (fileId == null || fileId <= 0) {
            throw new IllegalArgumentException("无效的文件 ID。");
        }
        if (userId == null || userId <= 0) {
            throw new IllegalArgumentException("无效的用户 ID。");
        }
        if (targetParentId != null && "".equals(targetParentId)) {
            targetParentId = null;
        }

        Integer version = chartConfigsUserMapper.selectVersionByFileId(fileId);
        if (version == null) {
            throw new RuntimeException("文件不存在，无法移动。");
        }

        // 更新的行数
        int rowsUpdated = chartConfigsUserMapper.moveFile(fileId, targetParentId, userId, version);
        if (rowsUpdated > 0) {
            log.info("文件移动成功: fileId={}, targetParentId={}, userId={}", fileId, targetParentId, userId);
            return true;
        } else {
            log.warn("文件移动失败，可能由于版本号不匹配: fileId={}, targetParentId={}, userId={}, version={}", fileId, targetParentId, userId, version);
            return false;
        }
    }










    // 修改 buildTree 方法名为 buildUpdatedTree
    private List<ChartFolderTreeDTO> buildUpdatedTree(List<ChartFolderTreeDTO> folderList,
                                                      Map<Long, List<ChartRecordDTO>> filesByFolderId,
                                                      Long parentId) {
        return folderList.stream()
                // 如果 parentId 是 null 则选择根层级，或者 parentId 相等的情况下才会递归添加到子层级
                .filter(folder -> (parentId == null && folder.getParentId() == null) ||
                        (parentId != null && parentId.equals(folder.getParentId())))
                .map(folder -> {
                    // 设置文件列表，file_id 为空的文件也会在根层级
                    if (parentId == null) {
                        List<ChartRecordDTO> rootFiles = filesByFolderId.get(null);
                        if (rootFiles != null) {
                            folder.setFiles(rootFiles);
                        }
                    }
                    folder.setFiles(filesByFolderId.get(folder.getFileId()));

                    // 递归查找子文件夹
                    folder.setChildren(buildUpdatedTree(folderList, filesByFolderId, folder.getFileId()));
                    return folder;
                })
                .collect(Collectors.toList());
    }

    // 修改文件夹转换方法名为 convertToUpdatedFolderTreeDTO
    private ChartFolderTreeDTO convertToUpdatedFolderTreeDTO(ChartFiles chartFile) {
        ChartFolderTreeDTO dto = new ChartFolderTreeDTO();
        dto.setFileId(chartFile.getFileId());
        //dto.setLabel(chartFile.getFileName());  // 使用 label 替代 fileName
        dto.setFileName(chartFile.getFileName());
        dto.setParentId(chartFile.getParentId());
        return dto;
    }

    // 修改图表记录转换方法名为 convertToUpdatedRecordDTO
    private ChartRecordDTO convertToUpdatedRecordDTO(ChartRecord chartRecord) {
        ChartRecordDTO dto = new ChartRecordDTO();
        dto.setId(chartRecord.getId());
        dto.setUserChartName(chartRecord.getUserChartName());
        dto.setFileId(chartRecord.getFileId());
        dto.setUserChartCover(chartRecord.getUserChartCover());
        dto.setUserChartOption(chartRecord.getUserChartOption());
        dto.setSource(chartRecord.getSource());
        dto.setStatus(chartRecord.getStatus());
        dto.setCreateTime(chartRecord.getCreateTime());
        dto.setUpdateTime(chartRecord.getUpdateTime());
        return dto;
    }




    @Override
    public List<ChartFolderTreeDTO> getUpdatedFolderFileTree(String name) {
        Long userId = SecurityUtils.getUserId();

        // 查询 chart_files 和 chart_record 表
        List<ChartFiles> allFolders = chartFilesMapper.selectFilesByName(name, userId);
        List<ChartRecord> allRecords = chartRecordMapper.selectRecordsByName(name, userId);  // 使用新表 chart_record

        if (name != null) {
            // 筛选匹配的文件夹
            List<ChartFolderTreeDTO> matchedFolders = allFolders.stream()
                    .filter(folder -> folder.getFileName() != null && folder.getFileName().contains(name))
                    .map(this::convertToUpdatedFolderTreeDTO)  // 使用新的转换方法
                    .collect(Collectors.toList());

            // 筛选匹配的图表记录（使用新的 chart_record）
            List<ChartRecordDTO> matchedRecords = allRecords.stream()
                    .filter(record -> record.getUserChartName() != null && record.getUserChartName().contains(name))
                    .map(this::convertToUpdatedRecordDTO)  // 转换为新的 ChartRecordDTO
                    .collect(Collectors.toList());

            if (!matchedFolders.isEmpty() || !matchedRecords.isEmpty()) {
                ChartFolderTreeDTO matchedNode = new ChartFolderTreeDTO();
                matchedNode.setLabel("我的生成");  // 使用 label 替代 fileName
                matchedNode.setChildren(matchedFolders);
                matchedNode.setFiles(matchedRecords);  // 更新为新的 ChartRecordDTO
                return Arrays.asList(matchedNode);
            }
        }

        // 将文件夹和记录都转为 DTO
        List<ChartFolderTreeDTO> folderDTOList = allFolders.stream()
                .map(this::convertToUpdatedFolderTreeDTO)  // 使用新的转换方法
                .collect(Collectors.toList());
        List<ChartRecordDTO> recordDTOList = allRecords.stream()
                .map(this::convertToUpdatedRecordDTO)  // 转换为新的 ChartRecordDTO
                .collect(Collectors.toList());

        // 根据文件夹 ID 分组图表记录
        Map<Long, List<ChartRecordDTO>> recordsByFolderId = recordDTOList.stream()
                .filter(record -> record.getFileId() != null)
                .collect(Collectors.groupingBy(ChartRecordDTO::getFileId));

        // 获取根目录下的图表记录
        List<ChartRecordDTO> rootRecords = recordDTOList.stream()
                .filter(record -> record.getFileId() == null)
                .collect(Collectors.toList());

        // 构建文件夹树
        List<ChartFolderTreeDTO> rootFolders = buildUpdatedTree(folderDTOList, recordsByFolderId, null);

        // 构建根节点，包含文件夹和图表记录
        ChartFolderTreeDTO rootNode = new ChartFolderTreeDTO();
        rootNode.setLabel("我的生成");  // 使用 label 替代 fileName
        rootNode.setFiles(rootRecords);  // 更新为 ChartRecordDTO
        rootNode.setChildren(rootFolders);

        return Arrays.asList(rootNode);
    }











}
